/*
#include "vfx_drops.h"

#include "background/bg_editor.h"
#include "background/bg_scene.h"
#include "dd/dd_man.h"
#include "font/font_manager.h"
#include "graphics/graphics_util.h"
#include "graphics/graphics.h"
#include "num/rand.h"
#include "part2d/part2d.h"
#include "script/scripthelper.h"
#include "script/write_lua.h"
#include "luaplus/LuaState.h"

#include "util/timer.h"				// log
#include "util/log.h"				// log
#include "util/common_macros.h"		// macros
#include "util/mmgr.h"		    

using namespace vfx;
using namespace editor;
using namespace background;
using namespace LuaPlus;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// VFXDrops

const std::string VFXDrops::ELEMENT_NAME = "VFXDrop";

VFXDrops::VFXDrops(EffectMan* pParent) : SFXSet(pParent),
	m_Acceleration(0.0f),
	m_Frequency(0.0f),
	m_Timer(0.0f),
	m_RandomDelay(0.0f),
	m_Delay(0.0f),
	m_pDropPart(NULL),
	m_pSplashPart(NULL)
{
}

VFXDrops::~VFXDrops()
{
	for (int i = 0; i < (int)m_Drops.size(); i++)
	{
		DROPLET& drop = m_Drops[i];
		//UTIL_SAFE_DELETE(drop.pDropPart);
		UTIL_SAFE_DELETE(drop.pSplashPart);
	}
	m_Drops.resize(0);

	UTIL_SAFE_DELETE(m_pDropPart);
	UTIL_SAFE_DELETE(m_pSplashPart);
}

void VFXDrops::Load(const std::string& File)
{
	using namespace script;
	assert(!File.empty() && "File name is empty!!!");

	LuaPlus::LuaState* pState = ScriptHelper::CreateLuaState();
	if (!ScriptHelper::DoFile(*pState, File))
	{
		_LOG(MSG_ERROR, "Unable to load VFXDrop file " << File << "!");
	 	LuaState::Destroy(pState);
		return;
	}
	else
	{
		LuaPlus::LuaObject Obj = ScriptHelper::GetObj(*pState, ELEMENT_NAME);
		if (Obj.IsTable())
		{
			Load(Obj);
		}
	}

	LuaState::Destroy(pState);
}

void VFXDrops::Load(LuaPlus::LuaObject& Obj)
{
	using namespace script;
	assert(Obj.IsTable() && "LuaObject Obj is not a table!!!");

	m_VFXName					= ScriptHelper::GetTableString(Obj, "VFXName", ELEMENT_NAME);

	std::string DropSprite		= ScriptHelper::GetTableString(Obj, "DropSprite");
	std::string SplashSprite	= ScriptHelper::GetTableString(Obj, "SplashSprite");
	std::string DropPart		= ScriptHelper::GetTableString(Obj, "DropPart");
	std::string SplashPart		= ScriptHelper::GetTableString(Obj, "SplashPart");

	math::Vec2 From				= ScriptHelper::GetTableVec2(Obj, "From", math::Vec2(0.5f, 0.0f));
	math::Vec2 To				= ScriptHelper::GetTableVec2(Obj, "To", math::Vec2(0.5f, 1.0f));
	math::Vec2 WiggleZone		= ScriptHelper::GetTableVec2(Obj, "WiggleZone");

	float Acceleration			= ScriptHelper::GetTableFloat(Obj, "Acceleration", 1.0f);
	float Frequency				= ScriptHelper::GetTableFloat(Obj, "Frequency", 1.0f);
	float RandomDelay			= ScriptHelper::GetTableFloat(Obj, "RandomDelay", 0.0f);

	Init(DropSprite, SplashSprite, DropPart, SplashPart);
	Setup(From, To, Acceleration, Frequency);
	SetWiggleZone(WiggleZone);
	SetRandomDelay(RandomDelay);
}

void VFXDrops::Save(script::WriteLua* pWL)
{
	using namespace script;
	assert(pWL);

	pWL->WritePair("VFXName",		m_VFXName);

	if (m_DropSprite.IsValid())		pWL->WritePair("DropSprite",	m_DropSprite.GetFilename());
	if (m_SplashSprite.IsValid())	pWL->WritePair("SplashSprite",	m_SplashSprite.GetFilename());
	if (!m_DropPart.empty())		pWL->WritePair("DropPart",		m_DropPart);
	if (!m_SplashPart.empty())		pWL->WritePair("SplashPart",	m_SplashPart);

	pWL->WritePair("From",			m_From);
	pWL->WritePair("To",			m_To);
	pWL->WritePair("Acceleration",	m_Acceleration);
	pWL->WritePair("Frequency",		m_Frequency);

	if (m_RandomDelay > 0.0f)
		pWL->WritePair("RandomDelay",	m_RandomDelay);

	if ((m_WiggleZone.x > 0.0f) || (m_WiggleZone.y > 0.0f))
		pWL->WritePair("WiggleZone",	m_WiggleZone);
}

void VFXDrops::Init(const std::string& DropSprite, const std::string& SplashSprite, const std::string& DropPart, const std::string& SplashPart)
{
	m_DropSprite.Create(DropSprite);
	m_SplashSprite.Create(SplashSprite);
	m_DropPart = DropPart;
	m_SplashPart = SplashPart;

	m_DropSize = m_DropSprite.m_Size;
	m_SplashSize = m_SplashSprite.m_Size;

	UTIL_SAFE_DELETE(m_pDropPart);
	if (!m_DropPart.empty())
	{
		m_pDropPart = new part2d::Part2D();
		m_pDropPart->Load(m_DropPart);
	}

	UTIL_SAFE_DELETE(m_pSplashPart);
	if (!m_SplashPart.empty())
	{
		m_pSplashPart = new part2d::Part2D();
		m_pSplashPart->Load(m_SplashPart);
	}

	m_Timer = 0.0f;
	m_Delay = 0.0f;

	// cache a bunch of drops on init?
	InitCache();
}

void VFXDrops::Init(VFXDrops* pFrom)
{
	assert(pFrom);
	m_VFXName = pFrom->m_VFXName;
	Init(pFrom->m_DropSprite.GetFilename(), pFrom->m_SplashSprite.GetFilename(), pFrom->m_DropPart, pFrom->m_SplashPart);
	Setup(pFrom->m_From, pFrom->m_To, pFrom->m_Acceleration, pFrom->m_Frequency);
	SetWiggleZone(pFrom->m_WiggleZone);
	SetRandomDelay(pFrom->m_RandomDelay);
}

void VFXDrops::InitCache(int Size)
{
	while (Size < (int)m_Drops.size())
		CreateNewDrop(false);
}

void VFXDrops::Setup(const math::Vec2& From, const math::Vec2& To, float Acceleration, float Frequency)
{
	m_From = From;
	m_To = To;

	if (Acceleration > 0.0f)	m_Acceleration = Acceleration;
	if (Frequency > 0.0f)		m_Frequency = Frequency;

	m_Dir = m_To - m_From;
	if (m_Dir.Magnitude() > 0.0001f)
	{
		m_Dir.Normalize();
	} else
	{
		m_Dir.x = 0;
		m_Dir.y = 1;
	}

	// NOTE: we can probably determine max # visible and cache elements based on Acceleration, Frequency and distance...
	//       the relevant formula should be s = ut + 0.5at^2 to determine total lifetime for 1 drop
	//       and then factor in frequency
}

void VFXDrops::Clear()
{
	for (int i = 0; i < (int)m_Drops.size(); i++)
	{
		DROPLET& drop = m_Drops[i];
		drop.IsAllocated = false;
	}
	m_AllocC = 0;
}

void VFXDrops::RenderDebug(const math::Vec2& Offset, float Scale)
{
	const float RENDER_DEBUG_RADIUS = 5.0f * GraphicsUtil::InvW;

	dd::Manager::Instance().AddCircle2D(m_From-Offset, RENDER_DEBUG_RADIUS, ColorRGBA(0,255,0,200));
	dd::Manager::Instance().AddLine2D(m_From-Offset, m_To-Offset, ColorRGBA(0,255,0,200));

	if ((m_WiggleZone.x > 0.0f) || (m_WiggleZone.y > 0.0f))
	{
		dd::Manager::Instance().AddBox2D(m_From-m_WiggleZone-Offset, m_From+m_WiggleZone-Offset, ColorRGBA(0,255,0,100));
		dd::Manager::Instance().AddBox2D(m_To-m_WiggleZone-Offset, m_To+m_WiggleZone-Offset, ColorRGBA(0,255,0,100));
	}
}

void VFXDrops::Render(const math::Vec2& Offset, float Scale)
{
	static std::vector<BATCH_RENDER> RenderDrops;
	static std::vector<BATCH_RENDER> RenderSplashes;

	m_DropSprite.m_Size = Scale * m_DropSize;
	m_SplashSprite.m_Size = Scale * m_SplashSize;

	if (m_pDropPart) m_pDropPart->Render(Offset, Scale);

	for (int i = 0; i < (int)m_Drops.size(); i++)
	{
		DROPLET& drop = m_Drops[i];
		if (!drop.IsAllocated) continue;

		//if (drop.pDropPart)
		//	drop.pDropPart->Render(Offset, Scale);

		if (!drop.HasSplashed && m_DropSprite.IsValid())
		{
			//RenderSprite(&m_DropSprite, drop.Pos - Offset - (0.5f * m_DropSprite.m_Size), drop.Time);
			BATCH_RENDER r;
			r.Time = drop.Time;
			r.Pos = drop.Pos - Offset - (0.5f * m_DropSprite.m_Size);
			RenderDrops.push_back(r);
		}

		if (!drop.HasSplashed) continue;

		if (drop.pSplashPart)
			drop.pSplashPart->Render(Offset, Scale);

		if (!drop.SplashCounter.IsReady() && m_SplashSprite.IsValid())
		{
			//RenderSprite(&m_SplashSprite, drop.To - Offset - (0.5f * m_SplashSprite.m_Size), drop.Time);
			BATCH_RENDER r;
			r.Time = drop.Time;
			r.Pos = drop.To - Offset - (0.5f * m_SplashSprite.m_Size);
			RenderSplashes.push_back(r);
		}
	}

	// batch render all sprites in two passes
	if (!RenderDrops.empty())
	{
		BatchRender(RenderDrops, &m_DropSprite);
		RenderDrops.clear();
	}
	if (!RenderSplashes.empty())
	{
		BatchRender(RenderSplashes, &m_SplashSprite);
		RenderSplashes.clear();
	}
}

void VFXDrops::Tick(float dt)
{
	// check creation
	bool ResetDelay = false;
	m_Timer += dt;
	while ((m_Frequency > 0.0f) && (m_Timer > (m_Frequency + m_Delay)))
	{
		DROPLET& drop = m_Drops[CreateNewDrop()];
		math::Vec2 Wiggle;

		if (m_WiggleZone.x > 0.0f)	Wiggle.x = num::RAND32::Instance().RandFloat(-m_WiggleZone.x, m_WiggleZone.x);
		if (m_WiggleZone.y > 0.0f)	Wiggle.y = num::RAND32::Instance().RandFloat(-m_WiggleZone.y, m_WiggleZone.y);
		
		drop.Pos = drop.Origin = m_From + Wiggle;
		drop.To = m_To + Wiggle;
		drop.Dir = m_Dir;

		drop.Velocity = 0.0f;
		drop.Acceleration = m_Acceleration;
		drop.Time = 0.0f;

		drop.SplashCounter.SetLimit(m_SplashSprite.GetTotalAnimTime());
		drop.SplashCounter.Reset();

		drop.HasSplashed = false;

		m_Timer -= m_Frequency;
		ResetDelay = true;
	}
	if (ResetDelay)
	{
		m_Delay = (m_RandomDelay > 0.0f) ? num::RAND32::Instance().RandFloat(0.0f, m_RandomDelay) : 0.0f;
	}

	// tick existing drops
	for (int i = 0; i < (int)m_Drops.size(); i++)
	{
		DROPLET& drop = m_Drops[i];
		if (!drop.IsAllocated) continue;

		if (drop.HasSplashed)
		{
			bool CanTryDelete = drop.SplashCounter.IsReady();
			if (!CanTryDelete)
			{
				drop.SplashCounter.Tick(dt);
				CanTryDelete = drop.SplashCounter.IsReady();
			}

			//if (drop.pDropPart)
			//	drop.pDropPart->Tick(dt);

			if (!CanTryDelete && m_DropSprite.IsValid())
				m_DropSprite.UpdateTime(drop.Time, dt);

			if (drop.pSplashPart)
			{
				drop.pSplashPart->Tick(dt);
				if (CanTryDelete && !drop.pSplashPart->IsActive())
					DeleteDrop(i);
			}
			else
			{
				if (CanTryDelete)
					DeleteDrop(i);
			}
		}
		else
		{
			if (m_SplashSprite.IsValid())
				m_SplashSprite.UpdateTime(drop.Time, dt);

			//if (drop.pDropPart)
			//{
			//	drop.pDropPart->TickCreation(dt, drop.Pos - (0.5f * m_DropSprite.m_Size), m_DropSprite.m_Size);
			//	drop.pDropPart->Tick(dt);
			//}
			if (m_pDropPart) m_pDropPart->TickCreation(dt, drop.Pos - (0.5f * m_DropSprite.m_Size), m_DropSprite.m_Size);

			math::Vec2 prevdir, curdir;

			prevdir = drop.To - drop.Pos;
			drop.Velocity += dt * drop.Acceleration;
			drop.Pos += (dt * drop.Velocity) * drop.Dir;
			curdir = drop.To - drop.Pos;

			if (curdir.MagSqr() > prevdir.MagSqr())
			{
				// dropped, now splash
				drop.Pos = drop.To;
				drop.Time = 0.0f;
				drop.HasSplashed = true;

				if (drop.pSplashPart)
				{
					// trigger splash part
					for (int g = 0; g < drop.pSplashPart->GroupC(); g++)
					{
						for (int c = 0; c < drop.pSplashPart->GetGroup(g)->GetMaxC(); c++)
							drop.pSplashPart->GetGroup(g)->TriggerParticle(drop.Pos);
					}
				}
			}
		}
	}

	// drop part is now a shared obj
	if (m_pDropPart) m_pDropPart->Tick(dt);
}

void VFXDrops::GetBoundingBox(math::Vec2& From, math::Vec2& To)
{
	// just calculate off current base? or take into account existing drop variations???
	From.x = UTIL_LOW(m_From.x-m_WiggleZone.x, m_To.x+m_WiggleZone.x);
	From.y = UTIL_LOW(m_From.y-m_WiggleZone.y, m_To.y+m_WiggleZone.y);
	To.x = UTIL_HIGH(m_From.x-m_WiggleZone.x, m_To.x+m_WiggleZone.x);
	To.y = UTIL_HIGH(m_From.y-m_WiggleZone.y, m_To.y+m_WiggleZone.y);

	From.x -= 0.5f * ( UTIL_HIGH(m_DropSprite.m_Size.x, m_SplashSprite.m_Size.x) );
	From.y -= 0.5f * ( UTIL_HIGH(m_DropSprite.m_Size.y, m_SplashSprite.m_Size.y) );
	To.x += 0.5f * ( UTIL_HIGH(m_DropSprite.m_Size.x, m_SplashSprite.m_Size.x) );
	To.y += 0.5f * ( UTIL_HIGH(m_DropSprite.m_Size.y, m_SplashSprite.m_Size.y) );
}

int VFXDrops::CreateNewDrop(bool Alloc)
{
	if (Alloc && (m_AllocC < (int)m_Drops.size()))
	{
		for (int i = 0; i < (int)m_Drops.size(); i++)
		{
			DROPLET& drop = m_Drops[i];
			if (!drop.IsAllocated)
			{
				if (drop.IsAllocated = Alloc)
					m_AllocC++;
				return i;
			}
		}
	}

	// no more unallocated drops; let's create a new one
	DROPLET drop;
	m_Drops.push_back(drop);

	DROPLET& newdrop = m_Drops[m_Drops.size()-1];

	//if (m_pDropPart)
	//	newdrop.pDropPart = m_pDropPart->Clone();
	//else
	//	newdrop.pDropPart = NULL;

	if (m_pSplashPart)
		newdrop.pSplashPart = m_pSplashPart->Clone();
	else
		newdrop.pSplashPart = NULL;

	if (newdrop.IsAllocated = Alloc)
		m_AllocC++;

	return (int)(m_Drops.size() - 1);
}

void VFXDrops::DeleteDrop(int idx)
{
	assert((idx >= 0) && (idx < (int)m_Drops.size()));

	DROPLET& drop = m_Drops[idx];
	drop.IsAllocated = false;

	//if (drop.pDropPart)		drop.pDropPart->Clear();
	if (drop.pSplashPart)	drop.pSplashPart->Clear();

	m_AllocC--;
}

/*
void VFXDrops::RenderSprite(ui::UISprite* pSprite, const math::Vec2& Pos, float Timer)
{
	Graphics::Vertex2D* VertA = Graphics::GetTempVert();
	Graphics* pG = GetGraphics();
	assert(pSprite && VertA && pG);

	if (ui::SpriteInstance* pInst = pSprite->GetSpriteInst())
	{
		math::Vec2 UV1, UV2;

		pInst->GetUV(Timer, UV1, UV2);
		GraphicsUtil::FillRotatedQuad(pSprite->m_QuadRotation,
									  Pos,
									  pSprite->m_Size,
									  UV1,
									  UV2,
									  pSprite->m_Color,
									  VertA);
		pSprite->SetTexture();
		if (pSprite->IsAdditive()) pG->SetupAdditiveAlpha(true);
		pG->DrawVertex2D(VertA, 6);
		if (pSprite->IsAdditive()) pG->SetupAdditiveAlpha(false);
	}
}
*/
/*
void VFXDrops::BatchRender(std::vector<BATCH_RENDER>& Set, ui::UISprite* pSprite)
{
	Graphics::Vertex2D* VertA = Graphics::GetTempVert();
	Graphics* pG = GetGraphics();
	int Idx = 0;
	math::Vec2 UV1, UV2;

	assert(pSprite && VertA && pG);

	if (ui::SpriteInstance* pInst = pSprite->GetSpriteInst())
	{
		for (int i = 0; i < (int)Set.size(); i++)
		{
			BATCH_RENDER& r = Set[i];
			pInst->GetUV(r.Time, UV1, UV2);
			GraphicsUtil::FillRotatedQuad(pSprite->m_QuadRotation,
										  r.Pos,
										  pSprite->m_Size,
										  UV1,
										  UV2,
										  pSprite->m_Color,
										  &VertA[Idx]);
			Idx += 6;
			if ((Idx + 6) >= Graphics::MAX_TEMP_VERT)
			{
				// flush now!
				pSprite->SetTexture();
				if (pSprite->IsAdditive()) pG->SetupAdditiveAlpha(true);
				pG->DrawVertex2D(VertA, Idx);
				if (pSprite->IsAdditive()) pG->SetupAdditiveAlpha(false);
				Idx = 0;
			}
		}
	}

	if (Idx > 0)
	{
		pSprite->SetTexture();
		if (pSprite->IsAdditive()) pG->SetupAdditiveAlpha(true);
		pG->DrawVertex2D(VertA, Idx);
		if (pSprite->IsAdditive()) pG->SetupAdditiveAlpha(false);
	}
}



/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// BGDropFX

BGDropFX::BGDropFX(BGScene* pScene) : BGElement(pScene)
{
	assert(pScene);
	SetupCustom(VFXDrops::ELEMENT_NAME);
}

BGDropFX::~BGDropFX()
{
}

void BGDropFX::Render(const math::Vec2& Offset, float Scale)
{
	m_VFXDrops.Render(Offset, Scale);
}

void BGDropFX::RenderDebug(const math::Vec2& Offset, float Scale)
{
	BGElement::RenderDebug(Offset, Scale);
	m_VFXDrops.RenderDebug(Offset, Scale);
}

void BGDropFX::Tick(float dt)
{
	BGElement::Tick(dt);
	m_VFXDrops.Tick(dt);
}

void BGDropFX::Load(LuaPlus::LuaObject& Obj)
{
	BGElement::Load(Obj);
	m_VFXDrops.Load(Obj);
}

void BGDropFX::Save(script::WriteLua* pWL)
{
	BGElement::Save(pWL);
	m_VFXDrops.Save(pWL);
}

void BGDropFX::RecalcBoundingBox()
{
	math::Vec2 From, To;
	m_VFXDrops.GetBoundingBox(From, To);
	m_Pos = From;
	m_Size = To - From;
	BGElement::RecalcBoundingBox();
}

void BGDropFX::FlushImages()
{
	m_VFXDrops.Clear();
}

void BGDropFX::Setup(VFXDrops* pFrom)
{
	m_VFXDrops.Init(pFrom);
}

BGElement* BGDropFX::Create(BGScene* pScene)
{
	BGDropFX* pElement = new BGDropFX(pScene);
	return pElement;
}

void BGDropFX::RegisterMe(int KeyID)
{
	static bool IsRegistered = false;
	if (!IsRegistered)
	{
		BGScene::RegisterComponent(VFXDrops::ELEMENT_NAME, BGDropFX::Create, KeyID, VFXDropBrush::Create);
		IsRegistered = true;
	}
}

void BGDropFX::CopyData(BGElement*	pFrom)
{
	assert(pFrom && (GetType() == pFrom->GetType()));
	BGElement::CopyData(pFrom);
	m_VFXDrops.Init( &((BGDropFX*)pFrom)->GetDropObj() );
}



/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// VFXDropBrush

VFXDropBrush::VFXDropBrush(EditorMain* pEditor) : EditorBrush(pEditor),
	m_Stage(PLACE_ORIGIN),
	m_Frequency(1.0f),
	m_Acceleration(1.0f),
	m_SortVal(1.0f),
	m_pCurrent(NULL),
	m_CurrentIdx(0),
	m_pScene(NULL)
{
	assert(pEditor);
	if (pEditor == BGEditor::s_pBGEditor)
		m_pScene = BGEditor::s_pBGEditor->GetScene();
	/* this may be dangerous depending on future use, so let's not try this (for now)
	else
		m_pScene = ((BGEditor*)pEditor)->GetScene();

	*/
/*
}

VFXDropBrush::~VFXDropBrush()
{
	if (m_pCurrent && m_pScene)
	{
		m_pScene->DropElement(m_pCurrent);
		UTIL_SAFE_DELETE(m_pCurrent);
	}

	for (int i = 0; i < (int)m_Collection.size(); i++)
		delete m_Collection[i];
	m_Collection.resize(0);
}

void VFXDropBrush::Render(const math::Vec2& Offset, float Scale)
{
	if (!m_pCurrent) return;
	m_pCurrent->RenderDebug(Offset, Scale);
	//if (m_Stage > PLACE_ORIGIN)
	//	m_pCurrent->Render(Offset, Scale); // can only render once origin is placed

	float	LineS = 0.025f;
	float	StartY = 0.65f;
	if (m_pEditor->ShowHelp())
	{
		FontManager::Instance().Print(math::Vec2(0.02f, StartY+=LineS), "Layer : %.1f. [Up/Down for single steps, PgUp/PgDown for steps of 10]. >0 is above the game board, ", m_SortVal);
		if (!m_pCurrent->GetDropObj().GetVFXName().empty())
		{
			FontManager::Instance().Print(math::Vec2(0.02f, StartY+=LineS), "Name : %s", m_pCurrent->GetDropObj().GetVFXName().c_str());
		}
		if (SET_PARAMS == m_Stage)
		{
			FontManager::Instance().Print(math::Vec2(0.02f, StartY+=LineS), "Frequency: %5.2f\nGravity: %5.2f", m_Frequency, m_Acceleration);
		}
	}
}

void VFXDropBrush::Tick(float dt)
{
	const math::Vec2 MousePos = m_pEditor->GetMousePos();

	switch (m_Stage)
	{
	case PLACE_ORIGIN:
		m_From = MousePos;
		m_To = m_From + math::Vec2(0.0, 0.1f);
		break;
	case PLACE_DEST:
		m_To = MousePos;
		if (ShiftDown())
		{
			math::Vec2 Diff = MousePos - m_From;
			if (fabs(Diff.x) > fabs(Diff.y))
				m_To.y = m_From.y;
			else
				m_To.x = m_From.x;
		}
		break;
	case SET_PARAMS:
		m_Frequency = MousePos.x * (CtrlDown() ? 1.0f : 10.0f);
		m_Acceleration = MousePos.y * (ShiftDown() ? 10.0f : 1.0f);
		// clamp values?
		RefreshHelpText();
		break;
	}

	if (m_pCurrent)
	{
		m_pCurrent->GetDropObj().Setup(m_From, m_To, m_Acceleration, m_Frequency);
		m_pCurrent->RecalcBoundingBox();
		//if (m_Stage > PLACE_ORIGIN)
		//	m_pCurrent->Tick(dt);
	}
}

void VFXDropBrush::ReleaseLMB()
{
	if (m_pCurrent)
	{
		m_pCurrent->GetDropObj().Setup(m_From, m_To, m_Acceleration, m_Frequency);
		m_pCurrent->RecalcBoundingBox();
	}

	if (SET_PARAMS == m_Stage)
	{	
		m_pCurrent = NULL;
		Rotate(0);
	}
	else
	{
		m_Stage = (PLACE_STAGE)(m_Stage + 1);
		RefreshHelpText();
	}
}

bool VFXDropBrush::TryDelete(const math::Vec2& Pos)
{
	// need to temporarily displace from BGScene first
	if (m_pScene)
	{
		bool Deleted = false;
		if (m_pCurrent) m_pScene->DropElement(m_pCurrent);
		Deleted = m_pScene->DeleteElement(Pos);
		if (m_pCurrent) m_pScene->AddElement(m_pCurrent);
		return Deleted;
	}
	return false;
}

void VFXDropBrush::Raise(int Dir)
{
	if (m_pCurrent)
	{
		m_SortVal += float(Dir);
		m_pCurrent->SetSort(m_SortVal);
		if (m_pScene)
		{
			m_pScene->DropElement(m_pCurrent);
			m_pScene->AddElement(m_pCurrent);
		}
	}
}

void VFXDropBrush::Rotate(int Dir)
{
	if (m_Collection.empty()) return;
	if (!m_pScene) return;

	if (m_pCurrent)
	{
		m_pScene->DropElement(m_pCurrent);
		UTIL_SAFE_DELETE(m_pCurrent);
	}

	if (-1 == m_CurrentIdx)
		m_CurrentIdx = 0;
	else if (Dir > 0)
		m_CurrentIdx = (m_CurrentIdx+1) % m_Collection.size();
	else if (Dir < 0)
		m_CurrentIdx = (m_CurrentIdx > 0) ? (m_CurrentIdx - 1) : (int)(m_Collection.size()-1);

	m_pCurrent = new BGDropFX(m_pScene);
	m_pCurrent->GetDropObj().Init(m_Collection[m_CurrentIdx]);
	m_pCurrent->SetSort(m_SortVal);

	m_Stage = PLACE_ORIGIN;
	m_From = m_pEditor->GetMousePos();
	m_To = m_From + math::Vec2(0.0f, 0.1f);
	m_Frequency = 1.0f;
	m_Acceleration = 1.0f;
	
	m_pCurrent->GetDropObj().Setup(m_From, m_To, m_Acceleration, m_Frequency);
	m_pScene->AddElement(m_pCurrent);

	RefreshHelpText();
}

/*
void VFXDropBrush::RenderHelp()
{
	std::string HelpStr;

	switch (m_Stage)
	{
	case PLACE_ORIGIN:		HelpStr = "Place Origin"; break;
	case PLACE_DEST:		HelpStr = "Place Destination"; break;
	case SET_PARAMS:		HelpStr = "Set Parameters"; break;
	}

	if (!HelpStr.empty())
		FontManager::Instance().Print( m_pEditor->GetMousePos(), HelpStr.c_str() );
}
*/
/*
void VFXDropBrush::LoadSet(const std::string& File)
{
	using namespace script;
	assert(!File.empty() && "File name is empty!!!");

	LuaPlus::LuaState* pState = ScriptHelper::CreateLuaState();
	if (!ScriptHelper::DoFile(*pState, File))
	{
		_LOG(MSG_ERROR, "Unable to load VFXDrop collection " << File << "!");
		LuaState::Destroy(pState);
		return;
	}
	else
	{
		LuaPlus::LuaObject Obj = ScriptHelper::GetObj(*pState, VFXDrops::ELEMENT_NAME+"Collection");
		if (Obj.IsTable())
		{
			int TableC = Obj.GetTableCount();
			for (int i = 0; i < TableC; i++)
			{
				LuaPlus::LuaObject Element = Obj.GetByIndex(i+1);
				if (Element.IsTable())
				{
					vfx::VFXDrops* pDrop = new vfx::VFXDrops(NULL);
					pDrop->Load(Element);
					m_Collection.push_back(pDrop);
				}
			}
		}
	}

	Rotate(0);
	LuaState::Destroy(pState);
}

EditorBrush* VFXDropBrush::Create(EditorMain* pMain)
{
	VFXDropBrush* pBrush = new VFXDropBrush(pMain);
	// hardcoded data file loading, or...?
	pBrush->LoadSet("infos/vfx_drops.lua");
	return pBrush;
}

void VFXDropBrush::RefreshHelpText()
{
	std::string HelpStr;
	switch (m_Stage)
	{
	case PLACE_ORIGIN:		HelpStr = "Place Drop Origin"; break;
	case PLACE_DEST:		HelpStr = "Place Destination"; break;
	case SET_PARAMS:		HelpStr = "Set Parameters; [CTRL] Accelerate Frequency [SHIFT] Accelerate Gravity"; break;
	}

	if (!HelpStr.empty())
		m_HelpText = HelpStr;
}
*/
